/**
 * validatebox - jQuery xui
 *
 * Licensed under the GPL: http://www.gnu.org/licenses/gpl.txt
 *
 * Copyright 2015 xjb [ beymy.en@gmail.com ]
 *
 */
(function($) {
    function init(target) {
    };

    function bindEvents(target) {
        var opts = $.data(target, 'tooltip').options;
        var t = $(target);
        
        t.unbind('.tooltip');
        if(opts.showEvent) {
	        t.bind(opts.showEvent + '.tooltip', function(e) {
	            $(target).tooltip('show', e);
	        })
    	}
        if(opts.hideEvent) {
	        t.bind(opts.hideEvent + '.tooltip', function(e) {
	            $(target).tooltip('hide', e);
	        });
    	}
    };

    function clearTimer(target) {
        var state = $.data(target, 'tooltip');
        if (state.showTimer) {
            clearTimeout(state.showTimer);
            state.showTimer = null;
        }
        if (state.hideTimer) {
            clearTimeout(state.hideTimer);
            state.hideTimer = null;
        }
    };

    function reposition(target) {
        var state = $.data(target, 'tooltip');
        if (!state || !state.tip) {
            return;
        }
        var opts = state.options;
        var tip = state.tip;
        var position = {
            left: -100000,
            top: -100000
        };
        if ($(target).is(':visible')) {
            position = calcPosition(opts.position);
        }
        tip.css({
            left: position.left,
            top: position.top,
            zIndex: (opts.zIndex != undefined ? opts.zIndex : '') //TODO
        });

        function calcPosition(position) {
            opts.position = position || 'bottom';
            tip.removeClass('tooltip-top tooltip-bottom tooltip-left tooltip-right').addClass('tooltip-' + opts.position);
            var left, top;
            var t = $(target);
            left = t.offset().left + opts.deltaX;
            top = t.offset().top + opts.deltaY;
            switch (opts.position) {
                case 'right':
                    left += t._outerWidth() + 6;
                    top -= (tip._outerHeight() - t._outerHeight()) / 2;
                    break;
                case 'left':
                    left -= tip._outerWidth() + 6;
                    top -= (tip._outerHeight() - t._outerHeight()) / 2;
                    break;
                case 'top':
                    left -= (tip._outerWidth() - t._outerWidth()) / 2;
                    top -= tip._outerHeight() + 6;
                    break;
                case 'bottom':
                    left -= (tip._outerWidth() - t._outerWidth()) / 2;
                    top += t._outerHeight() + 6;
                    break;
            }
            return {
                left: left,
                top: top
            };
        };
    };

    function show(target, e) {
        var state = $.data(target, 'tooltip');
        var opts = state.options;
        var tip = state.tip;
        if (!tip) {
            tip = $('<div class="tooltip">'+
				'<div class="tooltip-content"></div>'+
				'<div class="tooltip-arrow-outer"></div>'+
				'<div class="tooltip-arrow"></div>'+
				'</div>').appendTo('body');
            state.tip = tip;
            update(target);
        }
        clearTimer(target);
        state.showTimer = setTimeout(function() {
            reposition(target);
            tip.show();
            opts.onShow.call(target, e);
            var outer = tip.children('.tooltip-arrow-outer');
            var arrow = tip.children('.tooltip-arrow');
            var bc = "border-" + opts.position + "-color";
            outer.add(arrow).css({
                borderTopColor: "",
                borderBottomColor: "",
                borderLeftColor: "",
                borderRightColor: ""
            });
            outer.css(bc, tip.css(bc));
            arrow.css(bc, tip.css("backgroundColor"));
        }, opts.showDelay);
    };

    function hide(target, e) {
        var state = $.data(target, 'tooltip');
        if (state && state.tip) {
            clearTimer(target);
            state.hideTimer = setTimeout(function() {
                state.tip.hide();
                state.options.onHide.call(target, e);
            }, state.options.hideDelay);
        }
    };

    function update(target, content) {
        var state = $.data(target, 'tooltip');
        var opts = state.options;
        if (content) {
            opts.content = content;
        }
        if (!state.tip) {
            return;
        }
        state.tip.find('.tooltip-content').html(opts.content);
        reposition(target);
        opts.onUpdate.call(target, opts.content);
    };

    function destroy(target) {
        var state = $.data(target, 'tooltip');
        if (state) {
            clearTimer(target);
            var opts = state.options;
            if (state.tip) {
                state.tip.remove();
            }

            $.removeData(target, 'tooltip');
            $(target).unbind('.tooltip');
            opts.onDestroy.call(target);
        }
    };
    $.fn.tooltip = function(options, param) {
        if (typeof options == 'string') {
            return $.fn.tooltip.methods[options](this, param);
        }
        options = options || {};
        return this.each(function() {
            var state = $.data(this, 'tooltip');
            if (state) {
                $.extend(state.options, options);
            } else {
                $.data(this, 'tooltip', {
                    options: $.extend({}, $.fn.tooltip.defaults, $.fn.tooltip.parseOptions(this), options)
                });
                init(this);
            }
            bindEvents(this);
            update(this);
        });
    };
    $.fn.tooltip.methods = {
        options: function(jq) {
            return $.data(jq[0], 'tooltip').options;
        },
        tip: function(jq) {
            return $.data(jq[0], 'tooltip').tip;
        },
        show: function(jq, e) {
            return jq.each(function() {
                show(this, e);
            });
        },
        hide: function(jq, e) {
            return jq.each(function() {
                hide(this, e);
            });
        },
        update: function(jq, content) {
            return jq.each(function() {
                update(this, content);
            });
        },
        destroy: function(jq) {
            return jq.each(function() {
                destroy(this);
            });
        }
    };
    $.fn.tooltip.parseOptions = function(target) {
        return $.parser.parseOptions(target);
    };
    $.fn.tooltip.defaults = {
        position: 'bottom',
        content: null,
        deltaX: 0,
        deltaY: 0,
        showEvent: 'mouseenter',
        hideEvent: 'mouseleave',
        showDelay: 100,
        hideDelay: 100,
        onShow: function(e) {},
        onHide: function(e) {},
        onUpdate: function(content) {},
        onDestroy: function() {}
    };
})(jQuery);
